home *** CD-ROM | disk | FTP | other *** search
- #include <math.h>
- #include <stdio.h>
- #include <string.h>
- #ifndef NOUNISTD_H
- #include <unistd.h>
- #endif
-
- #include "symbol.h"
- #include "code.h"
- #include "math.tab.h"
- #include "fudgit.h"
- #include "setshow.h"
- #include "head.h"
-
- static double *Pvec[4];
- static void yfit(double **der, double *par, double *vec, int ndata);
- static void fexpo(double *x, double *a, double *y, double **dyda, int ndata);
- static void fcosine(double *X, double **du, int ndata);
- static void fsine(double *X, double **du, int ndata);
- static void fgauss(double *x, double *a, double *y, double **dyda, int ndata);
- static void fpoly(double *X, double **du, int ndata);
- static void fleg(double *X, double **du, int ndata);
-
- extern double *Ft_X2;
- extern double *Ft_Param;
- extern void Ft_mathuser(void);
-
-
- extern void Ft_fit (double *x, double *y, int ndata, double *sig, int mwt, double *a, double *b, double *siga, double *sigb, double *chi2, double *q);
- extern void Ft_pearsn (double *x, double *y, int n, double *r, double *prob, double *z);
- extern void Ft_medfit (double *x, double *y, int ndata, double *a, double *b, double *abdev);
- extern int Ft_svdvar (double **v, int ma, double *w, double **cvm);
-
- int Ft_fits(int argc, char **argv, int ndata)
- {
- int i, j;
- Symbol *sym[4];
- char name[TOKENSIZE+10];
-
- extern int Ft_svdfit(double **coef, double *y, double *sig, int ndata, double *a, int ma, double **v, double *w, double *chisq);
- extern int Ft_lfit(double **coef, double *y, double *sig, int ndata, double *a, int ma, int *lista, int mfit, double **covar, double *chisq);
- extern int Ft_mrqmin(double **coef, double *f, double *y, double *sig, int ndata, double *a, int ma, int *lista, int mfit, double **covar, double **alpha, double *chisq, double *alamda);
- extern Symbol *Ft_lookup(char *s);
-
- /* printf("CHECK FOR STUPID MISTAKES\n"); */
- if (ndata == 0) {
- fputs("No data to fit!\n", stderr);
- return(ERRR);
- }
- else if ((int) *Ft_Param == 0) {
- fputs("You must set parameters first!\n", stderr);
- return(ERRR);
- }
- else if (Ft_Methi == NONE) {
- fputs("You must set method first!\n", stderr);
- return(ERRR);
- }
- else if (Ft_Funci == NONE) {
- fputs("You must set function first!\n", stderr);
- return(ERRR);
- }
- else if ((Ft_Methi == LS_FIT || Ft_Methi == ML_FIT) && Ft_Mlist == 0) {
- fprintf(stderr, "You must 'adjust' before fitting with '%s'.\n",
- Ft_Method[Ft_Methi].name);
- return(ERRR);
- }
- /* printf("LOOKUP-INSTALL FIT VARIABLES\n"); */
- for (i=0;i<argc-1;i++) {
- if ((sym[i] = Ft_lookup(argv[i+1])) == 0) {
- fprintf(stderr, "%s: No such variable.\n", argv[i+1]);
- return(ERRR);
- }
- else if (sym[i]->type != VEC) {
- fprintf(stderr, "%s: Not a vector.\n", argv[i+1]);
- return(ERRR);
- }
- Pvec[i] = sym[i]->u.vec;
- }
- /* printf("make fit vector\n"); */
- sprintf(name, "%sFIT", sym[1]->name);
- if ((sym[3] = Ft_lookup(name)) == 0) {
- sym[3] = Ft_install(name, VEC, Ft_Samples);
- }
- Pvec[3] = sym[3]->u.vec;
- for (i=1;i<= (int) *Ft_Param;i++) {
- sprintf(name, "D%sFITD%d", sym[1]->name, i);
- if ((sym[3] = Ft_lookup(name)) == 0) {
- sym[3] = Ft_install(name, VEC, Ft_Samples);
- }
- Ft_Mparxsamp[i] = sym[3]->u.vec;
- }
-
- /* printf("PREPARE PARTIAL DERIVATIVE MATRIX\n"); */
- /* here we start --- going Ft_Functionwise */
- if (Ft_Funci == POLY) {
- fpoly(Pvec[0], Ft_Mparxsamp, ndata);
- }
- else if (Ft_Funci == SINE) {
- fsine(Pvec[0], Ft_Mparxsamp, ndata);
- }
- else if (Ft_Funci == COSINE) {
- fcosine(Pvec[0], Ft_Mparxsamp, ndata);
- }
- else if (Ft_Funci == LEG) {
- fleg(Pvec[0], Ft_Mparxsamp, ndata);
- }
- else if (Ft_Funci == GAUSS) {
- if ((int) *Ft_Param%3) {
- fputs("Number of parameters not a multiple of 3.\n", stderr);
- return(ERRR);
- }
- if (Ft_Methi != ML_FIT) {
- fprintf(stderr, "'%s' can only be used with '%s'.\n",
- Ft_Function[Ft_Funci].name, Ft_Method[ML_FIT].name);
- return(ERRR);
- }
- fgauss(Pvec[0], Ft_A, Pvec[3], Ft_Mparxsamp, ndata);
- }
- else if (Ft_Funci == EXPO) {
- if ((int) *Ft_Param%2) {
- fputs("Number of parameters not a multiple of 2.\n", stderr);
- return(ERRR);
- }
- if (Ft_Methi != ML_FIT) {
- fprintf(stderr, "'%s' can only be used with '%s'.\n",
- Ft_Function[Ft_Funci].name, Ft_Method[ML_FIT].name);
- return(ERRR);
- }
- fexpo(Pvec[0], Ft_A, Pvec[3], Ft_Mparxsamp, ndata);
- }
- else if (Ft_Funci == STRL) {
- /* printf("IF STRAIGHT LINE DO IT NOW\n"); */
- if (Ft_Methi == SVD_FIT || Ft_Methi == LS_FIT) {
- fprintf(stderr, "Use a polynomial for '%s'!\n",
- Ft_Method[Ft_Methi].name);
- return(ERRR);
- }
- else if (Ft_Methi == LS_REG) {
- int dy = 1;
-
- if (argc == 3) {
- dy = 0;
- Pvec[2] = 0;
- }
- if ((int) *Ft_Param != 2) {
- fprintf(stderr, "2 parameters are needed for '%s'.\n",
- Ft_Method[LS_REG].name);
- return(ERRR);
- }
- fpoly(Pvec[0], Ft_Mparxsamp, ndata);
- Ft_fit(Pvec[0], Pvec[1], ndata, Pvec[2], dy,
- Ft_A+1, Ft_A+2, Ft_DA+1, Ft_DA+2, Ft_X2, &Ft_Q);
- yfit(Ft_Mparxsamp, Ft_A, Pvec[3], ndata);
- Ft_pearsn(Pvec[0], Pvec[1], ndata, Ft_Cortest, Ft_Cortest+1,
- Ft_Cortest+2);
- }
- else if (Ft_Methi == LA_REG) {
- if ((int) *Ft_Param != 2) {
- fprintf(stderr, "2 parameters are needed for '%s'.\n",
- Ft_Method[LA_REG].name);
- return(ERRR);
- }
- if (argc == 4) {
- fprintf(stderr, "Warning: Errors are not used in '%s'.\n",
- Ft_Method[LA_REG].name);
- }
- fpoly(Pvec[0], Ft_Mparxsamp, ndata);
- Ft_medfit(Pvec[0], Pvec[1], ndata, Ft_A+1, Ft_A+2, Ft_X2);
- yfit(Ft_Mparxsamp, Ft_A, Pvec[3], ndata);
- Ft_pearsn(Pvec[0], Pvec[1], ndata, Ft_Cortest,
- Ft_Cortest+1, Ft_Cortest+2);
- }
- else {
- fprintf(stderr, "Ft_Function '%s' is not supported under '%s'.\n",
- Ft_Function[Ft_Funci].name, Ft_Method[Ft_Methi].name);
- return(ERRR);
- }
- return(0);
- }
- else if (Ft_Funci == USER && Ft_Methi != ML_FIT) {
- Ft_mathuser();
- }
-
- /* printf("WHICH OTHER METHOD\n"); */
- /* Now going method wise */
- if (Ft_Methi == SVD_FIT) {
- if (Ft_svdfit(Ft_Mparxsamp, Pvec[1], Pvec[2],
- ndata, Ft_A, (int) *Ft_Param, Ft_M2parxpar, Ft_Mfparx1, Ft_X2) != ERRR) {
- Ft_svdvar(Ft_M2parxpar, (int) *Ft_Param, Ft_Mfparx1, Ft_M1parxpar);
- yfit(Ft_Mparxsamp, Ft_A, Pvec[3], ndata);
- for (i=1;i<= (int) *Ft_Param;i++) {
- Ft_DA[i] = sqrt(Ft_M1parxpar[i][i]);
- }
- }
- }
- else if (Ft_Methi == LS_FIT) {
- if (Ft_lfit(Ft_Mparxsamp, Pvec[1], Pvec[2], ndata,
- Ft_A, (int) *Ft_Param, Ft_Miparx1, Ft_Mlist, Ft_M1parxpar, Ft_X2) != ERRR) {
- yfit(Ft_Mparxsamp, Ft_A, Pvec[3], ndata);
- for (i=1;i<= (int) *Ft_Param;i++) {
- Ft_DA[i] = sqrt(Ft_M1parxpar[i][i]);
- }
- }
- }
- else if (Ft_Methi == ML_FIT) {
- int same = 0;
- double ox2 = 0.0;
- int iter = (Ft_Iter > 0? Ft_Iter : -Ft_Iter);
-
- Ft_Q = -1;
- if (Ft_mrqmin(Ft_Mparxsamp, Pvec[3], Pvec[1], Pvec[2], ndata, Ft_A,
- (int) *Ft_Param, Ft_Miparx1, Ft_Mlist, Ft_M1parxpar,
- Ft_M2parxpar, Ft_X2, &Ft_Q) == ERRR) {
- return(ERRR);
- }
- for (i=1; i<= iter;i++) {
- if (Ft_mrqmin(Ft_Mparxsamp, Pvec[3], Pvec[1], Pvec[2], ndata, Ft_A,
- (int) *Ft_Param, Ft_Miparx1, Ft_Mlist, Ft_M1parxpar, Ft_M2parxpar,
- Ft_X2, &Ft_Q) == ERRR) {
- break;
- }
- fprintf(stderr, "~~~~~~~~~~ Iteration: %02d ~~~~~~~~~~~~\t", i);
- fprintf(stderr, "%s: ", "Chi^2");
- fprintf(stderr, Ft_Format, *Ft_X2);
- fprintf(stderr, "\n");
- ox2 = *Ft_X2 -ox2;
- fprintf(stderr, "%45s: ", "DChi^2");
- fprintf(stderr, Ft_Format, ox2);
- fputc('\n', stderr);
- for (j=1;j <= (int) *Ft_Param;j++) {
- char buffer[128];
- sprintf(buffer, "%s[%d]", Ft_Pname, j);
- fprintf(stderr, "%20s: ", buffer);
- fprintf(stderr, Ft_Format, Ft_A[j]);
- fputc('\n', stderr);
- }
- if (Ft_Iter > 0) { /* check for convergence if Iter > 0 */
- if (ox2 == (double)0.0)
- same++;
- else
- same = 0;
- if (same == 2) {
- fprintf(stderr, "Convergence after %d iterations.\n", i);
- break;
- }
- ox2 = *Ft_X2;
- }
- }
- Ft_Q = 0.0;
- if (Ft_mrqmin(Ft_Mparxsamp, Pvec[3], Pvec[1], Pvec[2], ndata, Ft_A,
- (int) *Ft_Param, Ft_Miparx1, Ft_Mlist, Ft_M1parxpar,
- Ft_M2parxpar, Ft_X2, &Ft_Q) == ERRR) {
- return(ERRR);
- }
- for (i=1;i<= (int) *Ft_Param;i++) {
- Ft_DA[i] = sqrt(Ft_M1parxpar[i][i]);
- }
- }
- else {
- fprintf(stderr, "Ft_Function '%s' is not supported under '%s'.\n",
- Ft_Function[Ft_Funci].name, Ft_Method[Ft_Methi].name);
- return(ERRR);
- }
- return(0);
- }
-
- void Ft_fml_fit(int ndata)
- {
- extern void Ft_mathuser(void);
-
- switch(Ft_Funci) {
- case USER:
- Ft_mathuser();
- return;
- case GAUSS:
- fgauss(Pvec[0], Ft_A, Pvec[3], Ft_Mparxsamp, ndata);
- return;
- case EXPO:
- fexpo(Pvec[0], Ft_A, Pvec[3], Ft_Mparxsamp, ndata);
- return;
- }
- }
-
- /* linear */
- static void fleg(double *X, double **du, int ndata)
- {
- int i, j;
- double twox,f2,f1,d;
-
- if (Ft_Methi != LS_FIT && Ft_Methi != SVD_FIT) {
- fprintf(stderr,
- "Legendre series not supported under '%s' method.\n",
- Ft_Method[Ft_Methi].name);
- Ft_catcher(ERRR);
- }
- for (i=1; i<= ndata; i++) {
- du[1][i]=1.0;
- du[2][i]=X[i];
- if ((int) *Ft_Param > 2) {
- twox=2.0*X[i];
- f2=X[i];
- d=1.0;
- for (j=3;j<=(int) *Ft_Param;j++) {
- f1=d;
- d += 1.0;
- f2 += twox;
- du[j][i]=(f2*du[j-1][i]-f1*du[j-2][i])/d;
- }
- }
- }
- return;
- }
-
- /* linear */
- static void fpoly(double *X, double **du, int ndata)
- {
- int i, j;
-
- if (Ft_Methi == ML_FIT) {
- fprintf(stderr,
- "Power series not supported under '%s' method.\n",
- Ft_Method[Ft_Methi].name);
- Ft_catcher(ERRR);
- }
- for (i=1;i<=ndata;i++) {
- du[1][i]=1.0;
- for (j=2;j<=(int) *Ft_Param;j++) du[j][i]=du[j-1][i]*X[i];
- }
- return;
- }
-
- static void fgauss(double *x, double *a, double *y, double **dyda, int ndata)
- /* non-linear */
- {
- int i, j;
- double fac, ex, arg;
-
- for (j=1;j<= ndata;j++) {
- y[j]=0.0;
- for (i=1;i<=(int) *Ft_Param-1;i+=3) {
- arg=(x[j]-a[i+1])/a[i+2];
- ex=exp(-arg*arg);
- fac=a[i]*ex*2.0*arg;
- y[j] += a[i]*ex;
- dyda[i][j]=ex;
- dyda[i+1][j]=fac/a[i+2];
- dyda[i+2][j]=fac*arg/a[i+2];
- }
- }
- return;
- }
-
- static void fsine(double *X, double **du, int ndata) /* linear */
-
-
- {
- int i, j;
-
- if (Ft_Methi != LS_FIT && Ft_Methi != SVD_FIT) {
- fprintf(stderr,
- "Sine series not supported under '%s' method.\n",
- Ft_Method[Ft_Methi].name);
- Ft_catcher(ERRR);
- }
- for (i=1;i<= ndata;i++) {
- for (j=1;j<= (int) *Ft_Param;j++) {
- du[j][i] = sin(j*X[i]);
- }
- }
- return;
- }
-
- static void fcosine(double *X, double **du, int ndata) /* linear */
-
-
- {
- int i, j;
-
- if (Ft_Methi != LS_FIT && Ft_Methi != SVD_FIT) {
- fprintf(stderr,
- "Sine series not supported under '%s' method.\n",
- Ft_Method[Ft_Methi].name);
- Ft_catcher(ERRR);
- }
- for (i=1;i<= ndata;i++) {
- du[1][i] = 1.0;
- for (j=2; j<= (int) *Ft_Param;j++) {
- du[j][i] = cos((j-1)*X[i]);
- }
- }
- return;
- }
-
- static void fexpo(double *x, double *a, double *y, double **dyda, int ndata) /* non-linear */
-
-
- {
- int i, j;
- double ex, arg;
-
- for (j=1;j <= ndata;j++) {
- y[j] = 0.0;
- for (i=1;i<=(int) *Ft_Param-1;i+=2) {
- arg = (x[j] * a[i+1]);
- ex = exp(arg);
- y[j] += a[i] * ex;
- dyda[i][j] = ex;
- dyda[i+1][j] = a[i] * a[i+1] * ex;
- }
- }
- return;
- }
-
- /* rebuild the function from the partial(total) linear derivatives */
- /* not valid for non-linear fits */
- static void yfit(double **der, double *par, double *vec, int ndata)
- {
- int i, j;
-
- for (j=1;j<=ndata;j++) {
- vec[j] = 0.0;
- }
- for (i=1;i<=(int) *Ft_Param;i++) {
- for (j=1;j<=ndata;j++) {
- vec[j] += par[i]*der[i][j];
- }
- }
- return;
- }
-